/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.dbtools.dbconnect;

import java.util.*;
import java.io.*;

import jdbcmanager.app.*;

/**
 * Defines a connection.
 * <p>
 * Used to pass a connection definition to certain methods.<br>
 * Defintion can be read from a file and save to a file (i.e. for predefined connections),
 * or can be created on the fly.
 *  
 * @author Francisco Morero Peyrona
 */

public class ConnectionDefinition
{   
   // Properties of *.connect files -------------------------------//  
   private static final String DRIVER_ID = "driver_id";
   private static final String URL       = "url";
   private static final String USER      = "user";
   private static final String PASSWORD  = "password";
   private static final String CATALOG   = "catalog";
   //----------------------------------------------------------//
   
   private String sDriverId = null;
   private String sURL      = null;
   private String sUser     = null;
   private char[] sPassword = null;   // char[] instead of String to protect password from RAM explorers
   private String sCatalog  = null;
   
   //-------------------------------------------------------------------------//
   
   public ConnectionDefinition()
   {
      super();
   }
   
   public ConnectionDefinition( String sDriverId, String sURL, String sUser, String sPassword, String sCatalog )
   {
      setDriverId( sDriverId );
      setURL( sURL );
      setUser( sUser );
      setPassword( sPassword );
      setCatalog( sCatalog );
   }
   
   public ConnectionDefinition( String sFileName )
   {
      load( new File( App.getUserDir(), normalizeFileName( sFileName ) ) );
   }
   
   public ConnectionDefinition( File file )
   {
      load( file );
   }
   
   public String getDriverId() { return this.sDriverId; }
   public String getURL()      { return this.sURL;      }
   public String getUser()     { return this.sUser;     }
   public String getPassword() { return this.sPassword == null ? null: String.valueOf( this.sPassword ); }
   public String getCatalog()  { return this.sCatalog;  }
   
   public void setDriverId( String s ) { this.sDriverId = (s == null) ? null : s.trim(); }
   public void setURL( String s )      { this.sURL      = (s == null) ? null : s.trim(); }
   public void setUser( String s )     { this.sUser     = s; }  // Can start and/or end with spaces and be null
   public void setPassword( String s ) { this.sPassword = s == null ? null : s.toCharArray(); }  // Can start and end with spaces and be null
   public void setCatalog( String s )  { this.sCatalog  = (s == null) ? null : s.trim(); }   
   
   public void load( File file )
   {
      try
      {
         Properties      prop = new Properties();
         FileInputStream fis  = new FileInputStream( file );

         prop.load( fis );

         setDriverId( prop.getProperty( DRIVER_ID ) );
         setURL(      prop.getProperty( URL       ) );
         setUser(     prop.getProperty( USER      ) );
         setPassword( prop.getProperty( PASSWORD  ) );
         setCatalog(  prop.getProperty( CATALOG   ) );
         
         fis.close();
      }
      catch( IOException exc )
      {
         App.showException( exc, "Error reading file" );
      }      
   }
   
   public void save( String sFileName )
   {
      save( new File( App.getUserDir(), normalizeFileName( sFileName ) ) );
   }
   
   public void save( File file )
   {
      try
      {
         save( new BufferedWriter( new FileWriter( file, false ) ), 
               "# User Predefined Connection in a Connection Definition File ("+ App.sCONNECTION_FILE_EXT +")" );
      }
      catch( IOException exc )
      {
         App.showException( exc, "Error saving file" );
      }
   }
   
   /**
    * Checks that exists and that it is a file.
    * 
    * @param  sFileName  File name to check
    * @return <code>true</code> if exists and is a file
    */
   public static boolean exists( String sFileName )
   {
      File f = new File( App.getUserDir(), normalizeFileName( sFileName ) );
      
      return (f.exists() && f.isFile());
   }
   
   /**
    * 
    * @param sFileName
    * @return
    */
   public static boolean delete( String sFileName )
   {
      File f = new File( App.getUserDir(), normalizeFileName( sFileName ) );
      
      boolean bRet = f.delete();
      
      if( ! bRet )
         App.showMessage( "Error deleting file", "Can't delete '"+ f.getAbsolutePath() +"'." );
      
      return bRet;
   }
   
   /**
    * 
    * @return
    */
   public static File[] listFiles()
   {      
      File[] aFile = App.getUserDir().listFiles( new FileFilter()
                     {
                        public boolean accept( File f )  
                        { 
                           return f.getName().endsWith( App.sCONNECTION_FILE_EXT ); 
                        }
                     } );
                     
      return aFile;
   }
   
   /**
    * Called by public save(...)
    *  
    * @param  bw A BufferedWriter
    * @param  sHeader A String
    * @throws IOException If something goes wrong
    */
   protected void save( BufferedWriter bw, String sHeader ) throws IOException
   {
      // These keys can't be null, because without them, a connection can not defined
      if( getDriverId() == null || getURL() == null )
         throw new NullPointerException( "Neither \"DriverId\", nor \"URL\" can be null." );
      
      bw.write( sHeader ); bw.newLine();
      bw.newLine();      
      bw.write( StrWise.padR( DRIVER_ID, 10 ) +" = "+ getDriverId() );  bw.newLine();
      bw.write( StrWise.padR( URL      , 10 ) +" = "+ getURL() );
      
      // Following keys are not written in the file if their values are null because Properties.getProperty() 
      // returns null if the key does not exists, but returns "" if the key exists
      
      if( getUser() != null )
      {
         bw.newLine();
         bw.write( StrWise.padR( USER, 10 ) +" = "+ getUser() );  
      }

      if( getPassword() != null )
      {
         bw.newLine();
         bw.write( StrWise.padR( PASSWORD, 10 ) +" = "+ getPassword() );
      }
      
      if( getCatalog() != null )
      {
         bw.newLine();
         bw.write( StrWise.padR( CATALOG, 10 ) +" = "+ getCatalog() );
      }

      bw.close();
   }
   
   protected static String normalizeFileName( String sFileName )
   {
      sFileName = sFileName.trim();
      
      if( sFileName.length() > 0 )
      {
         if( ! sFileName.endsWith( App.sCONNECTION_FILE_EXT ) )
            sFileName += App.sCONNECTION_FILE_EXT;
      }
      
      return sFileName;
   }
}